//------------------------------------------------------------
//  Filename: vga_driver.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2016-10-08 10:54
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module VGA_DRIVER ( 
     // Users to add ports here
     input wire         clk_vga,  
     input wire         rst    ,
     
     output reg [7:0]   vga_R,
     output reg [7:0]   vga_G,
     output reg [7:0]   vga_B,
     output reg         vga_h_sync,  
     output reg         vga_v_sync,
     output reg         vga_de,
 
     input  wire        disp_bar_en,   
     output wire        disp_rd_clk,
     output wire        disp_rd_en,
     input  wire [32:0] disp_dout,
     input  wire        disp_empty
);
//--------------------------------------------------------
localparam VLINES   = 525; //vga_disp_hvcnt[15:0] ; 
localparam HPIXELS  = 800; //vga_disp_hvcnt[31:16]; 
localparam HL_PIXS  = 4;   //vga_disp_hvcnt[31:16]; 
localparam VL_LINES = 3;   //vga_disp_hvcnt[31:16]; 
localparam HBP      = 46;  //vga_disp_hconf[15:0] ; 
localparam HFP      = 526; //vga_disp_hconf[31:16]; 
localparam VBP      = 14;  //vga_disp_vconf[15:0] ; 
localparam VFP      = 286; //vga_disp_vconf[31:16]; 
//--------------------------------------------------------
reg [9:0] h_counter;
reg [9:0] v_counter;
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        h_counter<=0;
    end 
    else if(h_counter==HPIXELS) begin
        h_counter<=0;
    end
    else begin
        h_counter<=h_counter+1;
    end
end
//--------------------------------------------------------
reg vs_enable;
always@(posedge clk_vga ) vs_enable<=(h_counter==HPIXELS)?1:0; 
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        v_counter<=0;
    end 
    else if(vs_enable==1) begin
        v_counter<=(v_counter==VLINES)?0:(v_counter+1);
    end 
end
//--------------------------------------------------------
reg h_sync;
reg v_sync;
always@(posedge clk_vga) h_sync <= (h_counter<HL_PIXS)?0:1;
always@(posedge clk_vga) v_sync <= (v_counter<VL_LINES)?0:1;
//--------------------------------------------------------
assign disp_rd_clk   = clk_vga;
wire   data_rd_en    = (h_counter<HFP)&&(h_counter>=HBP)&&(v_counter<VFP)&&(v_counter>=VBP);
assign disp_rd_en    = data_rd_en;   //video channel 0
//--------------------------------------------------------
reg in_bar;
reg data_rd_en_ff1;
reg[23:0] disp_dout_ff1;
always@(posedge clk_vga) data_rd_en_ff1 <= data_rd_en; 
always@(posedge clk_vga) disp_dout_ff1  <= disp_dout[23:0]; 
//--------------------------------------------------------
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        in_bar <= 1'b0;        
    end 
    else if((disp_bar_en)&&
            (v_counter > (VBP + 222))&&
            (v_counter < (VBP + 262))&&
            (h_counter < (HBP + 470))&&
            (h_counter > (HBP + 10))) begin    
        in_bar <= 1'b1;        
    end 
    else begin
        in_bar <= 1'b0;        
    end
end 
//--------------------------------------------------------
localparam TICK_PERIOD = 400000;
//--------------------------------------------------------
reg[31:0] tick_cntr;
//--------------------------------------------------------
always@(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        tick_cntr <= 32'b0;        
    end 
    else if(tick_cntr >= TICK_PERIOD)begin //10ms per tick
        tick_cntr <= 32'b0;        
    end    
    else if(disp_bar_en) begin
        tick_cntr <= tick_cntr + 32'b1;        
    end
end
//--------------------------------------------------------
reg[11:0] bar_fill;
//--------------------------------------------------------
always@(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        bar_fill  <= 12'h0;
    end 
    else if(tick_cntr >= TICK_PERIOD)begin
        bar_fill  <= bar_fill + 12'h1;
    end 
end 
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        vga_R <= 8'h0;
        vga_G <= 8'h0;
        vga_B <= 8'h0;         
    end 
    else if(data_rd_en_ff1)begin 
        if(disp_bar_en&in_bar) begin
            vga_R <= 8'h0;        
            vga_G <= (h_counter < bar_fill)?8'hff:8'h0;
            vga_B <= (h_counter < bar_fill)?8'h88:8'h0;
        end
        else begin
            vga_R <= disp_dout_ff1[23:16];
            vga_G <= disp_dout_ff1[15:8];
            vga_B <= disp_dout_ff1[7:0];
        end    
    end 
    else begin
        vga_R <= 8'h0;
        vga_G <= 8'h0;
        vga_B <= 8'h0;         
    end
end 
//--------------------------------------------------------
// delay 5 cycle  
reg[3:0] h_sync_ff;
reg[3:0] v_sync_ff;
reg[3:0] vga_de_ff;
always@(posedge clk_vga) h_sync_ff <= {h_sync_ff[2:0],h_sync};
always@(posedge clk_vga) v_sync_ff <= {v_sync_ff[2:0],v_sync};   
always@(posedge clk_vga) vga_de_ff <= {vga_de_ff[2:0],data_rd_en};   
//--------------------------------------------------------
always @(posedge clk_vga,posedge rst) begin
    if(rst)begin 
        vga_h_sync <= 1'b0;
        vga_v_sync <= 1'b0;
        vga_de     <= 1'b0;            
    end 
    else begin 
        vga_h_sync <= h_sync_ff[1];
        vga_v_sync <= v_sync_ff[1];
        vga_de     <= vga_de_ff[0];            
    end 
end 
//--------------------------------------------------------
// User logic ends

endmodule

